package xx.services;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import xx.db.QueryRunner;
import xx.db.sql.Owner;
import xx.services.util.Constants;
import xx.services.util.Names;
import xx.services.util.Results;
import xx.util.ip.IPSeeker;
import xx.util.string.Format;

/**
 * 通行证
 * 
 * @author chenx,2010-9-1 $LastChangedDate$ $Author$
 */
public abstract class Passport
{
    protected static Log logger = LogFactory.getLog(Passport.class);

    protected final HttpServletRequest request;

    /**
     * 返回JSON数据格式
     */
    protected static final int JSON = Results.JSON;

    /**
     * 返回XML数据格式
     */
    protected static final int XML = Results.XML;

    /**
     * 返回HTML数据格式
     */
    protected static final int HTML = Results.HTML;

    /** 接收的数据格式:application/xml,text/xml,application/json,text/json,text/html,text/plain */
    protected final String accept;

    /** 接收的数据类型：Results.JSON，Results.XML，Results.HTML，默认为Results.JSON */
    protected final int type;

    /**
     * 当前登陆人对象
     */
    public final Owner owner;

    public final QueryRunner qr;

    /**
     * 当前登陆人的userId
     */
    public final long userId;

    public final HttpSession session;

    // 通用变量
    /**
     * 每页显示多少条数据
     */
    protected final int pageSize;

    /**
     * 页码
     */
    protected final int pageNo;

    /** 是否需要返回总页数 */
    protected final boolean isTotal;

    /**
     * 查询条件
     */
    protected final String condition;

    /**
     * 排序字段
     */
    protected final String orderField;

    /**
     * 返回的字段集，为空时表示返回有所字段
     */
    protected final String fields;

    /**
     * 访问者ip
     */
    protected final String ip;

    /**
     * 构造函数
     * 
     * @param userId
     * @author chenx,2010-9-1
     */
    public Passport(HttpServletRequest request)
    {
        this.request = request;
        Enumeration names = request.getHeaderNames();
        while (names.hasMoreElements())
        {
            String name = "" + names.nextElement();
            System.out.println(name + ":" + request.getHeader(name));
            if (name.equals(Constants.X_FORWARDED_FOR))
            {
                System.out.println("来自于：" + IPSeeker.getInstance().getAddress(request.getHeader(name)));
            }
        }

        System.out.println("参数：");
        Enumeration<String> e = request.getParameterNames();
        while (e.hasMoreElements())
        {
            String name = e.nextElement();
            System.out.println(name + "=" + request.getParameter(name));
        }
        this.session = request.getSession();

        Object oUserId = session.getAttribute(Constants.USER_ID);
        this.userId = oUserId == null || "".equals(oUserId.toString().trim()) ? 0 : Long.parseLong(oUserId.toString());
        this.owner = new Owner(this.userId, this.userId);

        this.qr = new QueryRunner(Names.FRAMEWORK, owner);

        this.pageSize = Format.strToInt(getParameter(Constants.PAGESIZE), Constants.PAGESIZE_DEFAULT);
        this.pageNo = Format.strToInt(getParameter(Constants.PAGENO), Constants.PAGENO_DEFAULT);
        this.isTotal = Format.strToBoolean(getParameter(Constants.IS_TOTAL), Constants.IS_TOTAL_DEFAULT || this.pageNo == 1);
        this.condition = getParameter(Constants.CONDITION);
        this.orderField = getParameter(Constants.ORDERFIELD);
        this.fields = getParameter(Constants.FIELDS);
        this.ip = getClientIp(request);// request.getHeader("x-forworded-for");
        this.accept = request.getHeader("accept");
        if (accept != null)
            this.type = accept.indexOf("application/xml") >= 0 || accept.indexOf("text/xml") >= 0 ? Results.XML : accept.indexOf("application/json") >= 0
                    || accept.indexOf("text/json") >= 0 ? Results.JSON : accept.indexOf("text/html") >= 0 || accept.indexOf("text/plain") >= 0 ? Results.HTML : Results.JSON;
        else
            this.type = Results.JSON;

        qr.setAutoCommit("GET".equalsIgnoreCase(request.getMethod()));
    }

    /**
     * 将url后边的参数与FormParam参数放到Map中
     * 
     * @param is
     *            也就是form表单提交时的数据流
     * @return
     */
    protected Map<String, Object> getParams(InputStream is)
    {
        Map<String, Object> map = new HashMap<String, Object>();
        try
        {
            String enc = "utf-8";
            byte[] bt = new byte[is.available()];
            is.read(bt);
            String s = new String(bt);
            String[] pars = s.split("&");
            for (String par : pars)
            {
                String[] val = par.split("=");
                if (val.length < 2)
                    continue;
                map.put(val[0], URLDecoder.decode(val[1], enc));
            }
        }
        catch (IOException e)
        {
            logger.error(loggerError(e));
        }

        Enumeration<String> e = request.getParameterNames();
        while (e.hasMoreElements())
        {
            String name = e.nextElement();
            map.put(name, request.getParameter(name));
        }

        if (map.containsKey("res_id"))// 将resId作为key放入到map中，将map转为entity是需要用到
            map.put("key", map.get("res_id"));

        return map;
    }

    /**
     * 获取客户端的IP
     * 
     * @param request
     * @return
     */
    private static String getClientIp(HttpServletRequest request)
    {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getRemoteAddr();
        }

        if (ip.indexOf(",") != -1)
        {
            ip = ip.substring(0, ip.indexOf(","));
        }

        return ip;
    }

    /**
     * 操作成功，默认JSON格式数据返回到客户端
     * 
     * @param msg
     *            返回到客户端的消息
     * @return
     * @throws SQLException
     */
    protected String ok(Object msg) throws SQLException
    {
        return ok(msg, type);
    }

    /**
     * 操作成功，默认JSON格式数据返回到客户端
     * 
     * @param msg
     *            返回到客户端的消息
     * @param other
     *            其他值
     * @return
     * @throws SQLException
     */
    protected String ok(Object msg, Map<String, Object> other) throws SQLException
    {
        if (!qr.isAutoCommit())
            qr.commit();

        Results results = new Results();
        return results.succeed(msg, other);
    }

    /**
     * 操作成功
     * 
     * @param msg
     *            返回到客户端的消息
     * @param dataType
     *            返回的数据类型[JSON｜XML｜HTML]
     * @return
     */
    protected String ok(Object msg, int dataType) throws SQLException
    {
        if (!qr.isAutoCommit())
            qr.commit();

        Results results = new Results(dataType);
        return results.succeed(msg);
    }

    /**
     * 出错了，默认JSON格式数据返回到客户端
     * 
     * @param msg
     *            返回到客户端的消息
     * @return
     */
    protected String error(Object msg)
    {
        return error(msg, type);
    }

    /**
     * 出错了
     * 
     * @param msg
     *            返回到客户端的消息
     * @param dataType
     *            返回的数据类型[JSON｜XML｜HTML]
     * @return
     */
    protected String error(Object msg, int dataType)
    {
        // 发布时删除
        if (msg instanceof Exception)
        {
            Exception e = (Exception) msg;
            // e.printStackTrace();

            msg = e.getMessage();
            logger.error(loggerError(e));
        }
        else
        {
            // System.out.println(msg.toString());
            logger.error(msg);
        }

        if (!qr.isAutoCommit())
            qr.rollback();

        Results results = new Results(dataType);
        return results.error(msg);
    }

    /**
     * 警告，默认JSON格式数据返回到客户端
     * 
     * @param msg
     *            返回到客户端的消息
     * @return
     */
    protected String warning(Object msg)
    {
        return warning(msg, type);
    }

    /**
     * 警告
     * 
     * @param msg
     *            返回到客户端的消息
     * @param dataType
     *            返回的数据类型[JSON｜XML｜HTML]
     * @return
     */
    protected String warning(Object msg, int dataType)
    {
        Results results = new Results(dataType);
        return results.warning(msg);
    }

    protected String getParameter(String key, String def)
    {
        // Enumeration<String> e = request.getParameterNames();
        // while (e.hasMoreElements())
        // {
        // String name = e.nextElement();
        // System.out.println(name + "=" + request.getParameter(name));
        // }
        return Format.isEmpty(key) ? def : request.getParameter(key);
    }

    protected String getParameter(String key)
    {
        return getParameter(key, null);
    }

    protected String decode(String src, String en)
    {
        if (src == null)
            return src;
        try
        {
            return URLDecoder.decode(src, en);
        }
        catch (UnsupportedEncodingException e)
        {
            // TODO Auto-generated catch block
            // e.printStackTrace();
            logger.error(loggerError(e));
        }
        return null;
    }

    private String loggerError(Exception e)
    {
        StringBuilder sb = new StringBuilder();
        StackTraceElement[] stackTraceElementList = e.getStackTrace();
        sb.append(e).append("\n");
        for (StackTraceElement s : stackTraceElementList)
        {
            sb.append("\t\t\t\t\tat ").append(s.getClassName()).append(".").append(s.getMethodName()).append("(").append(s.getClassName()).append(".java:")
                    .append(s.getLineNumber()).append(")").append("\n");
        }
        return sb.toString();
    }

    /**
     * 获取上传文件对象
     * 
     * @return
     * @throws Exception
     */
    protected Upload getUpload() throws Exception
    {
        return new Upload(request);
    }
}
